The Schelling (1971) segregation model is a classic of agent-based modeling, demonstrating how agents following simple rules lead to the emergence of qualitatively different macro-level outcomes. Agents are randomly placed on a grid. There are two types of agents, one constituting the majority and the other the minority. All agents want a certain number (generally, 3) of their 8 surrounding neighbors to be of the same type in order for them to be happy. Unhappy agents will move to a random available grid space. While individual agents do not have a preference for a segregated outcome (e.g. they would be happy with 3 similar neighbors and 5 different ones), the aggregate outcome is nevertheless heavily segregated.
This is a demonstration of running a Mesa model in an IPython Notebook. The actual model and agent code are implemented in Schelling.py, in the same directory as this notebook. Below, we will import the model class, instantiate it, run it, and plot the time series of the number of happy agents.
In [1]:
import matplotlib.pyplot as plt
%matplotlib inline
from Schelling import model
Now we instantiate a model instance: a 10x10 grid, with an 80% change of an agent being placed in each cell, approximately 20% of agents set as minorities, and agents wanting at least 3 similar neighbors.
In [2]:
model = SchellingModel(10, 10, 0.8, 0.2, 3)
We want to run the model until all the agents are happy with where they are. However, there's no guarentee that a given model instantiation will ever settle down. So let's run it for either 100 steps or until it stops on its own, whichever comes first:
In [3]:
while model.running and model.schedule.steps < 100:
model.step()
print(model.schedule.steps) # Show how many steps have actually run
The model has a DataCollector object, which checks and stores how many agents are happy at the end of each step. It can also generate a pandas DataFrame of the data it has collected:
In [4]:
model_out = model.datacollector.get_model_vars_dataframe()
In [5]:
model_out.head()
Out[5]:
Finally, we can plot the 'happy' series:
In [6]:
model_out.happy.plot()
Out[6]:
For testing purposes, here is a table giving each agent's x and y values at each step.
In [7]:
x_positions = model.datacollector.get_agent_vars_dataframe()
In [8]:
x_positions.head()
Out[8]:
In [9]:
from mesa.batchrunner import BatchRunner
In [10]:
def get_segregation(model):
'''
Find the % of agents that only have neighbors of their same type.
'''
segregated_agents = 0
for agent in model.schedule.agents:
segregated = True
for neighbor in model.grid.neighbor_iter(agent.pos):
if neighbor.type != agent.type:
segregated = False
break
if segregated:
segregated_agents += 1
return segregated_agents / model.schedule.get_agent_count()
Now, we set up the batch run, with a dictionary of fixed and changing parameters. Let's hold everything fixed except for Homophily.
In [11]:
parameters = {"height": 10, "width": 10, "density": 0.8, "minority_pc": 0.2,
"homophily": range(1,9)}
In [12]:
model_reporters = {"Segregated_Agents": get_segregation}
In [13]:
param_sweep = BatchRunner(SchellingModel, parameters, iterations=10,
max_steps=200,
model_reporters=model_reporters)
In [14]:
param_sweep.run_all()
In [15]:
df = param_sweep.get_model_vars_dataframe()
In [16]:
plt.scatter(df.homophily, df.Segregated_Agents)
plt.grid(True)